import React, { useState, useEffect, useImperativeHandle, forwardRef } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { Button, Checkbox, Icon, Input, Select, Tooltip, Popconfirm, message } from 'antd';
import CheckboxGroup from 'antd/lib/checkbox/Group';
import { getAllPortTemplates, getProbeStrategyList, addProbeStrategy } from '@api/task';
import { PORT_RE, PORT_RANGE_RE } from '@util/constants';
import './render-probe-strategy.less';
import CutArray from '@util/cut-array';

const TextArea = Input.TextArea;
const RenderProbeStrategy = (props, ref) => {
  // eslint-disable-next-line react/prop-types
  const { typeName } = props;
  // 探测策略
  const [scanStrategy, setScanStrategy] = useState();
  const [selectedPortTemplate, setSelectedPortTemplate] = useState();
  const [portTemplateLoading, setPortTemplateLoading] = useState(false);
  const [portTemplates, setPortTemplates] = useState([]);
  const [portTemplatesMap, setPortTemplatesMap] = useState({});
  const [ports, setPorts] = useState();
  const [webFingerprintDetection, setWebFingerprintDetection] = useState(true);
  const [depthDetect, setDepthDetect] = useState(true);
  const [protocol, setProtocol] = useState([]);
  const [probeStrategyLoading, setProbeStrategyLoading] = useState(false);
  const [templateList, setTemplateList] = useState([]);
  const [checkTemplate, setCheckTemplate] = useState();
  const [portErro, setPortErro] = useState();
  const [protocolError, setProtocolError] = useState();
  const [templateName, seTemplateName] = useState();
  const [portDetectionOnly, setPortDetectionOnly] = useState();
  const [ignorePrinterPortCheck, setIgnorePrinterPortCheck] = useState();
  const [cachePortd, setcachePortd] = useState();
  const [cacheCustom, setCacheCustom] = useState();

  // 请求所有端口
  const loadPortTemplates = () => {
    setPortTemplateLoading(true);
    getAllPortTemplates().then(res => {
      const portTemplates = _.get(res, 'data.data.list', []);
      // 前端添加自定义选项
      portTemplates.push({ name: '自定义', _id: '01' });
      const portTemplatesMap = portTemplates.reduce((total, current = {}, index) => {
        total[current._id] = index;
        return total;
      }, {});

      setPortTemplates(portTemplates);
      setPortTemplatesMap(portTemplatesMap);
      setPortTemplateLoading(portTemplateLoading);
    });
  };

  // 请求所有模版
  const loadProbeStrategyList = id => {
    setProbeStrategyLoading(true);
    getProbeStrategyList({ page: 1, pageSize: 200 }).then(res => {
      // 前端添加自定义选项
      let list = _.get(res, 'data.data.results', []);
      list.push({ name: '自定义', _id: '01' });
      // 漏洞扫描的时候过滤端口探活检测模版
      if (typeName === 'VulDetect') {
        list = list.filter(r => !_.get(r, 'portDetectionOnly', false));
      }
      setTemplateList(list);
      let defaultItem;
      if (id) {
        defaultItem = _.find(list, i => i._id === id);
      } else {
        defaultItem = _.find(list, i => i.isDefault && i.name === '默认策略'); // 默认选择系统默认策略（名称为默认策略）
      }
      setScanStrategy(_.get(defaultItem, '_id'));
    });
    setProbeStrategyLoading(false);
  };
  // 端口触发事件
  const onPortTemplateChange = value => {
    const ports = _.get(portTemplates, `${portTemplatesMap[value]}.ports`, []);
    setSelectedPortTemplate(value);
    setPorts(ports);
    setIgnorePrinterPortCheck(false);
  };
  // 模版触发事件
  const changeStrategy = value => {
    setScanStrategy(value);
    if (value === '01') {
      const top1000 = portTemplates.filter(item => item.name === 'Top1000');
      setTimeout(() => {
        // 策略自定义=>端口Top1000
        top1000[0] && onPortTemplateChange(top1000[0]._id);
      }, 300);
    }
  };
  useEffect(() => {
    // 通过策略关联到端口
    if (scanStrategy) {
      setCheckTemplate(templateList.find(r => r._id === scanStrategy));
    }
  }, [scanStrategy]);

  // 端口校验
  const portsValidate = value => {
    let flag = '';
    if (!value) {
      flag = '端口不能为空';
    }
    let ports = value.split(',');
    ports.map(item => {
      if (!PORT_RE.test(item) && !PORT_RANGE_RE.test(item)) {
        flag = '请输入正确格式的端口';
      }
    });
    return flag;
  };

  const onChangeTextArea = value => {
    // 如果是自定义
    if (selectedPortTemplate === '01') {
      let erro = portsValidate(value.target.value);
      setPortErro(erro);
    } else {
      setPortErro();
    }

    setPorts(value.target.value);
  };

  const textAreaBlur = () => {
    if (ignorePrinterPortCheck) {
      // eslint-disable-next-line no-use-before-define
      changePorts(null, true);
    }
  };

  // 指纹
  const handleWebFingerChange = e => {
    let dprotocol = protocol;
    const value = e.target.checked;
    if (!dprotocol.includes('tcp')) {
      dprotocol.push('tcp');
    }
    setWebFingerprintDetection(value);
    setProtocol(dprotocol);
  };
  useEffect(() => {
    loadProbeStrategyList();
    loadPortTemplates();
  }, []);

  useEffect(() => {
    if (_.get(checkTemplate, 'protocolType', '')) {
      checkTemplate.protocolType = checkTemplate.protocolType.map(r => r.toLowerCase());
    }
    let Oid = _.get(checkTemplate, 'detectionPortOid._id', '') || '自定义';
    if (!cachePortd) {
      setSelectedPortTemplate(Oid);
      setPorts(
        _.get(checkTemplate, 'detectionPortList.length', 0) === 0
          ? _.get(checkTemplate, 'detectionPortOid.ports', [])
          : _.get(checkTemplate, 'detectionPortList', [])
      );
    }
    setDepthDetect(_.get(checkTemplate, 'depthDetect', true));
    setWebFingerprintDetection(_.get(checkTemplate, 'fingerprintDetection', true));
    setProtocol(_.get(checkTemplate, 'protocolType', ['icmp', 'udp', 'tcp']));
    setPortDetectionOnly(_.get(checkTemplate, 'portDetectionOnly', false));
    setIgnorePrinterPortCheck(_.get(checkTemplate, 'ignorePrinterPortCheck', false));
  }, [checkTemplate]);

  const popconfimInput = () => {
    return (
      <div>
        <Input
          value={templateName}
          onChange={e => seTemplateName(e.target.value)}
          placeholder="请输入模版名称"
        />
      </div>
    );
  };

  const check = () => {
    if (selectedPortTemplate === '01' && ports.length === 0) {
      message.error('端口为必填');
      return false;
    }
    if (protocolError) {
      message.error(protocolError);
      return false;
    }
    return true;
  };

  const changePorts = (e, checked) => {
    // 添加portTemplateLoading是因为策略模版数据没回来计算逻辑
    if ((ports && !portTemplateLoading && _.get(e, 'target.checked')) || checked) {
      setCacheCustom(ports);
      let newPorts = Array.isArray(ports) ? ports : ports.split(',');
      // eslint-disable-next-line eqeqeq
      newPorts = newPorts.filter(r => r != 9100);
      let newArray = [];
      for (let i = 0; i < newPorts.length; i++) {
        if (newPorts[i].split('').includes('-')) {
          // 排除值为 3 的项
          newArray.push(CutArray(newPorts[i]));
        } else {
          newArray.push(newPorts[i]);
        }
      }
      setPorts(newArray);
    } else {
      // 如果选中了模版 取消忽略的时候返回原来的值
      if (!_.get(e, 'target.checked') && selectedPortTemplate !== '01') {
        setcachePortd(selectedPortTemplate);
        loadProbeStrategyList(scanStrategy);
        onPortTemplateChange(selectedPortTemplate);
      } else if (!_.get(e, 'target.checked')) {
        setPorts(cacheCustom);
        setCacheCustom();
      }
    }
  };
  const submit = () => {
    if (!templateName) {
      message.error('请输入名称');
      return;
    }
    if (!check()) {
      return;
    }

    const body = {
      name: templateName,
      depthDetect: depthDetect,
      detectionPortId: selectedPortTemplate,
      fingerprintDetection: webFingerprintDetection,
      protocolType: protocol.map(r => r.toUpperCase()),
      detectionPortList: _.uniq(_.split(ports, ',')),
      isPortCustom: false,
      ignorePrinterPortCheck: ignorePrinterPortCheck || false,
      portDetectionOnly: portDetectionOnly || false
    };
    if (selectedPortTemplate === '01') {
      delete body.detectionPortId;
    }
    addProbeStrategy(body)
      .then(res => {
        message.success('添加成功');
        seTemplateName();
        loadProbeStrategyList(_.get(res, 'data.data.addDetectionStrategy._id', ''));
      })
      .catch(e => {
        message.error(e.message);
      });
  };

  useImperativeHandle(ref, () => ({
    data: {
      erro: {
        portErro,
        protocolError
      },
      detectionPortId: selectedPortTemplate,
      fingerprintDetection: webFingerprintDetection,
      portDetectionOnly: portDetectionOnly,
      protocolType: protocol,
      depthDetect: depthDetect,
      detectionPortList: _.uniq(_.split(ports, ',')),
      ignorePrinterPortCheck: ignorePrinterPortCheck,
      check
    }
  }));
  return (
    <>
      <div className={'item'}>
        <span className="item-title">探测策略</span>
        <Select
          defaultValue="默认策略"
          style={{ width: '100%' }}
          value={scanStrategy}
          onChange={changeStrategy}
          loading={probeStrategyLoading}
        >
          {templateList.map(r => (
            <Select.Option value={r._id} key={r._id}>
              {r.name}
            </Select.Option>
          ))}
        </Select>
      </div>
      <div
        className="item baselin port-template"
        style={{ width: typeName !== 'VulDetect' ? 800 : 600, marginLeft: 185 }}
      >
        {typeName !== 'VulDetect' && (
          <div className={'web-finger-detect'}>
            <span className="mr-r-10">
              仅端口探活
              <Tooltip title="系统会针对资产端口进行快速存活探测，如勾选此参数，则不会对存活端口进一步执行指纹探测、web指纹探测和操作系统深度探测操作。">
                <Icon type="exclamation-circle" style={{ marginLeft: 2, marginRight: 2 }} />
              </Tooltip>
            </span>
            <Checkbox
              disabled={
                _.get(checkTemplate, '_id', '') !== '01' || webFingerprintDetection || depthDetect
              }
              checked={portDetectionOnly}
              onChange={() => {
                setPortDetectionOnly(!portDetectionOnly);
              }}
            />
          </div>
        )}
        <div className={'web-finger-detect'}>
          <span className="mr-r-10">
            Web指纹探测
            <Tooltip title="系统会针对探测出来的具有http、https服务的端口进一步执行Web指纹探测。任务耗时会更长。">
              <Icon type="exclamation-circle" />
            </Tooltip>
          </span>
          <Checkbox
            disabled={_.get(checkTemplate, '_id', '') !== '01' || portDetectionOnly}
            checked={webFingerprintDetection}
            onChange={handleWebFingerChange}
          />
        </div>
        <div className={'web-finger-detect'}>
          <span className="mr-r-10">
            操作系统深度探测
            <Tooltip title="系统会对目标进行深度探测，识别到更多的操作系统信息，但也会影响扫描速度，任务耗时会更长。">
              <Icon type="exclamation-circle" style={{ marginLeft: 2, marginRight: 2 }} />
            </Tooltip>
          </span>
          <Checkbox
            disabled={_.get(checkTemplate, '_id', '') !== '01' || portDetectionOnly}
            checked={depthDetect}
            onChange={() => {
              setDepthDetect(!depthDetect);
            }}
          />
        </div>
        <div className={'protocol'}>
          <span className="required mr-l-10 mr-r-10">协议类型</span>
          <CheckboxGroup
            disabled={_.get(checkTemplate, '_id', '') !== '01'}
            className="protocol-group"
            value={protocol}
            onChange={protocol => {
              setProtocolError(_.isEmpty(protocol) ? '协议类型至少勾选一个' : '');
              setProtocol(protocol);
            }}
          >
            <Checkbox value="icmp">ICMP</Checkbox>
            <Checkbox value="udp">UDP</Checkbox>
            <Checkbox value="tcp" disabled={webFingerprintDetection}>
              TCP
            </Checkbox>
          </CheckboxGroup>
          <br />
          {<p className="validate-error-protocol">{protocolError}</p>}
        </div>
      </div>
      <div className="port-templates df flex-base">
        <div className="select-wrapper">
          <label className="mr-r-10 ">探测端口</label>
          <Select
            optionLabelProp="title"
            dropdownClassName="tm-asset-modal-select-drawdown"
            value={selectedPortTemplate}
            onChange={onPortTemplateChange}
            loading={portTemplateLoading}
            className={'mr-b-20'}
            style={{ width: 330 }}
            // 不是自定义都不能编辑
            disabled={scanStrategy !== '01'}
          >
            {portTemplates.map(portTemplate => (
              <Select.Option
                title={portTemplate.name}
                value={portTemplate._id}
                key={portTemplate._id}
              >
                <div className="template-item">
                  {portTemplate.name}
                  {selectedPortTemplate === portTemplate._id && <Icon type="check" />}
                </div>
              </Select.Option>
            ))}
          </Select>
        </div>
        <div className="web-finger-detect mr-l-10">
          <span className="mr-r-10">
            忽略网络打印机端口
            <Tooltip title="如勾选此参数,则下发扫描任务时会忽略网络打印机默认端口9100,避免打印机直接打印请求该端口的数据">
              <Icon type="exclamation-circle" style={{ marginLeft: 2, marginRight: 2 }} />
            </Tooltip>
          </span>
          <Checkbox
            disabled={_.get(checkTemplate, '_id', '') !== '01'}
            checked={ignorePrinterPortCheck}
            onChange={e => {
              setIgnorePrinterPortCheck(!ignorePrinterPortCheck);
              changePorts(e);
            }}
          />
        </div>
      </div>
      <div className="df pr">
        <TextArea
          className="ports"
          rows={5}
          value={ports}
          onChange={onChangeTextArea}
          placeholder='范围 0-65535 的整数。请使用
          "-" 指 定 端 口 范 围 ， 使 用 "," 分 隔 端 口 。 例 如 :
          21,22,23,10-50'
          disabled={_.get(checkTemplate, '_id', '') !== '01' || selectedPortTemplate !== '01'}
          style={{ width: '100%' }}
          onBlur={textAreaBlur}
        />
        {scanStrategy === '01' && (
          <a href="/asset-config/port-manage" className="go_port" target="_blank">
            前往进行端口管理
          </a>
        )}
      </div>
      {<p className="validate-error">{portErro}</p>}
      {scanStrategy === '01' && (
        <>
          <Popconfirm
            placement="top"
            title={popconfimInput()}
            icon={' '}
            overlayClassName="Popconfirm"
            onConfirm={submit}
            okText="保存"
            cancelText="取消"
          >
            <Button type="primary" size={'small'} className="mr-l-185 mr-b-20">
              保存为策略模版
            </Button>
          </Popconfirm>
          <Tooltip title="可将输入的参数保存为策略模板，方便下次下发任务时选用，如无需保存为模板，则输入的参数将作为本次任务下发">
            <Icon type="exclamation-circle" style={{ marginLeft: 5 }} />
          </Tooltip>
        </>
      )}
    </>
  );
};
RenderProbeStrategy.prototype = {
  onchange: PropTypes.func,
  typeName: PropTypes.string
};
export default forwardRef(RenderProbeStrategy);
